import os
import sys
import math
import warnings
import shutil
from PIL import Image, ImageFile
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                             QPushButton, QListWidget, QSlider, QLabel, QFileDialog,
                             QProgressBar, QCheckBox, QMessageBox, QGroupBox, QRadioButton,
                             QButtonGroup, QLineEdit, QSplitter, QListWidgetItem, QTableWidget,
                             QTableWidgetItem, QHeaderView, QFrame)
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QIcon, QPixmap, QDragEnterEvent, QDropEvent, QFont, QPalette, QColor

# 提高Pillow的像素限制以避免大图像警告
Image.MAX_IMAGE_PIXELS = 500000000  # 5亿像素限制
ImageFile.LOAD_TRUNCATED_IMAGES = True


class ConversionThread(QThread):
    """转换线程类，用于在后台执行转换操作"""
    progress_updated = pyqtSignal(int, int, str)  # 当前进度, 总数, 当前文件名
    conversion_finished = pyqtSignal()
    file_converted = pyqtSignal(str, int, int, float)  # 文件名, 原始大小, 新大小, 节省百分比

    def __init__(self, file_list, output_dir, quality, auto_resize, auto_rename):
        super().__init__()
        self.file_list = file_list
        self.output_dir = output_dir
        self.quality = quality
        self.auto_resize = auto_resize
        self.auto_rename = auto_rename
        self.is_running = True

    def run(self):
        total_files = len(self.file_list)
        for i, (file_path, _) in enumerate(self.file_list):
            if not self.is_running:
                break

            file_name = os.path.basename(file_path)
            self.progress_updated.emit(i + 1, total_files, file_name)

            try:
                # 为每个文件确定输出目录
                file_dir = os.path.dirname(file_path)
                if self.output_dir:  # 使用自定义输出目录
                    final_output_dir = self.output_dir
                else:  # 使用默认输出目录
                    final_output_dir = os.path.join(file_dir, 'webp_output')

                # 确保输出目录存在
                if not os.path.exists(final_output_dir):
                    os.makedirs(final_output_dir)

                # 获取原始文件大小
                original_size = os.path.getsize(file_path)

                # 转换文件
                new_size = self.convert_to_webp(file_path, final_output_dir, self.quality, self.auto_resize,
                                                self.auto_rename)

                if new_size > 0:
                    # 计算节省的百分比
                    saved_percent = ((original_size - new_size) / original_size) * 100
                    self.file_converted.emit(file_name, original_size, new_size, saved_percent)
            except Exception as e:
                print(f"Error converting {file_path}: {str(e)}")

        self.conversion_finished.emit()

    def stop(self):
        self.is_running = False

    def convert_to_webp(self, file_path, output_dir, quality, auto_resize, auto_rename):
        """将图片转换为WebP格式"""
        try:
            # 打开图像
            img = Image.open(file_path)

            # 自动调整大图像尺寸
            if auto_resize:
                max_dimension = 4000  # 最大维度
                if img.width > max_dimension or img.height > max_dimension:
                    # 计算新的尺寸，保持宽高比
                    if img.width > img.height:
                        new_width = max_dimension
                        new_height = int(img.height * max_dimension / img.width)
                    else:
                        new_height = max_dimension
                        new_width = int(img.width * max_dimension / img.height)

                    img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)

            # 转换为RGB模式（如果必要）
            if img.mode in ('RGBA', 'LA'):
                # 创建一个白色背景
                background = Image.new('RGB', img.size, (255, 255, 255))
                background.paste(img, mask=img.split()[-1])  # 使用alpha通道作为蒙版
                img = background
            elif img.mode != 'RGB':
                img = img.convert('RGB')

            # 生成输出文件名
            base_name = os.path.splitext(os.path.basename(file_path))[0]

            # 自动重命名
            if auto_rename:
                file_name = f"{base_name}_converted.webp"
            else:
                file_name = f"{base_name}.webp"

            output_path = os.path.join(output_dir, file_name)

            # 保存为WebP格式
            img.save(output_path, 'WEBP', quality=quality)

            # 返回新文件大小
            return os.path.getsize(output_path)

        except Exception as e:
            raise Exception(f"Failed to convert {file_path}: {str(e)}")

        return 0


class ImageConverter(QMainWindow):
    """主窗口类"""

    def __init__(self):
        super().__init__()
        self.file_list = []  # 存储文件路径和原始目录的元组列表
        self.conversion_thread = None
        self.conversion_results = []  # 存储转换结果
        self.total_original_size = 0  # 原始文件总大小

        self.setup_windows_classic_style()
        self.init_ui()
        self.setAcceptDrops(True)  # 启用拖放功能

    def setup_windows_classic_style(self):
        """设置Windows经典风格"""
        # 设置经典风格调色板
        palette = QPalette()
        palette.setColor(QPalette.Window, QColor(212, 208, 200))
        palette.setColor(QPalette.WindowText, Qt.black)
        palette.setColor(QPalette.Base, QColor(255, 255, 255))
        palette.setColor(QPalette.AlternateBase, QColor(233, 231, 227))
        palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 220))
        palette.setColor(QPalette.ToolTipText, Qt.black)
        palette.setColor(QPalette.Text, Qt.black)
        palette.setColor(QPalette.Button, QColor(212, 208, 200))
        palette.setColor(QPalette.ButtonText, Qt.black)
        palette.setColor(QPalette.BrightText, Qt.red)
        palette.setColor(QPalette.Link, QColor(0, 0, 255))
        palette.setColor(QPalette.Highlight, QColor(49, 106, 197))
        palette.setColor(QPalette.HighlightedText, Qt.white)

        # 设置应用程序调色板
        QApplication.setPalette(palette)

        # 设置经典风格字体
        font = QFont("MS Shell Dlg 2", 9)
        QApplication.setFont(font)

        # 设置样式表
        style = """
        QMainWindow, QDialog, QWidget {
            background-color: #D4D0C8;
        }
        QGroupBox {
            font-weight: bold;
            border: 2px solid #808080;
            border-radius: 4px;
            margin-top: 1ex;
            padding-top: 10px;
            background-color: #D4D0C8;
        }
        QGroupBox::title {
            subcontrol-origin: margin;
            subcontrol-position: top center;
            padding: 0 5px;
        }
        QPushButton {
            background-color: #D4D0C8;
            border: 2px solid #808080;
            border-radius: 3px;
            padding: 3px 12px;
            min-width: 75px;
            min-height: 23px;
        }
        QPushButton:pressed {
            background-color: #D4D0C8;
            border: 2px solid #808080;
            padding: 4px 11px 2px 13px;
        }
        QPushButton:disabled {
            color: #808080;
        }
        QListWidget {
            background-color: white;
            border: 2px solid #808080;
            border-radius: 3px;
        }
        QLineEdit {
            background-color: white;
            border: 2px solid #808080;
            border-radius: 3px;
            padding: 2px;
            min-height: 21px;
        }
        QSlider::groove:horizontal {
            border: 1px solid #808080;
            height: 6px;
            background: #D4D0C8;
            border-radius: 2px;
        }
        QSlider::handle:horizontal {
            background: #D4D0C8;
            border: 2px solid #808080;
            width: 18px;
            margin: -6px 0;
            border-radius: 3px;
        }
        QSlider::handle:horizontal:hover {
            background: #E4E0D8;
        }
        QProgressBar {
            border: 2px solid #808080;
            border-radius: 3px;
            text-align: center;
            background: #D4D0C8;
        }
        QProgressBar::chunk {
            background-color: #49A0FF;
            width: 10px;
        }
        QCheckBox, QRadioButton {
            spacing: 5px;
        }
        QCheckBox::indicator, QRadioButton::indicator {
            width: 13px;
            height: 13px;
        }
        QCheckBox::indicator {
            background: white;
            border: 2px solid #808080;
            border-radius: 2px;
        }
        QCheckBox::indicator:checked {
            background: #49A0FF;
        }
        QRadioButton::indicator {
            border: 2px solid #808080;
            border-radius: 7px;
            background: white;
        }
        QRadioButton::indicator:checked {
            background: #49A0FF;
        }
        QTableWidget {
            background-color: white;
            border: 2px solid #808080;
            border-radius: 3px;
            gridline-color: #D4D0C8;
        }
        QTableWidget::item {
            padding: 2px;
            border-right: 1px solid #D4D0C8;
            border-bottom: 1px solid #D4D0C8;
        }
        QTableWidget::item:selected {
            background-color: #49A0FF;
            color: white;
        }
        QHeaderView::section {
            background-color: #D4D0C8;
            border: 1px solid #808080;
            padding: 4px;
        }
        QLabel {
            background: transparent;
        }
        """
        self.setStyleSheet(style)

    def init_ui(self):
        """初始化用户界面"""
        self.setWindowTitle('图片转WebP转换器')
        self.setGeometry(100, 100, 1200, 800)  # 增加窗口宽度以容纳新表格

        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 主布局
        main_layout = QVBoxLayout(central_widget)
        main_layout.setSpacing(6)
        main_layout.setContentsMargins(8, 8, 8, 8)

        # 顶部按钮布局
        top_layout = QHBoxLayout()
        top_layout.setSpacing(4)

        self.select_files_btn = QPushButton('选择图片')
        self.select_files_btn.clicked.connect(self.select_files)
        top_layout.addWidget(self.select_files_btn)

        self.select_folder_btn = QPushButton('选择文件夹')
        self.select_folder_btn.clicked.connect(self.select_folder)
        top_layout.addWidget(self.select_folder_btn)

        self.clear_list_btn = QPushButton('清空列表')
        self.clear_list_btn.clicked.connect(self.clear_file_list)
        top_layout.addWidget(self.clear_list_btn)

        main_layout.addLayout(top_layout)

        # 创建分割器，左侧文件列表，右侧预览
        splitter = QSplitter(Qt.Horizontal)
        splitter.setHandleWidth(4)

        # 左侧面板（文件列表和选项）
        left_widget = QWidget()
        left_layout = QVBoxLayout(left_widget)
        left_layout.setSpacing(6)
        left_layout.setContentsMargins(4, 4, 4, 4)

        # 输出路径设置
        output_group = QGroupBox("输出设置")
        output_layout = QVBoxLayout(output_group)
        output_layout.setSpacing(4)
        output_layout.setContentsMargins(8, 16, 8, 8)

        # 输出路径选项
        path_option_layout = QHBoxLayout()
        path_option_layout.setSpacing(8)
        self.default_path_radio = QRadioButton("默认路径 (源文件夹/webp_output)")
        self.default_path_radio.setChecked(True)
        self.custom_path_radio = QRadioButton("自定义路径")
        path_option_layout.addWidget(self.default_path_radio)
        path_option_layout.addWidget(self.custom_path_radio)

        # 路径选项组
        self.path_option_group = QButtonGroup()
        self.path_option_group.addButton(self.default_path_radio)
        self.path_option_group.addButton(self.custom_path_radio)
        self.path_option_group.buttonClicked.connect(self.toggle_path_option)

        output_layout.addLayout(path_option_layout)

        # 自定义路径选择
        custom_path_layout = QHBoxLayout()
        custom_path_layout.setSpacing(4)
        self.custom_path_edit = QLineEdit()
        self.custom_path_edit.setPlaceholderText("选择或输入自定义输出路径")
        self.custom_path_edit.setEnabled(False)
        custom_path_layout.addWidget(self.custom_path_edit)

        self.browse_path_btn = QPushButton("浏览")
        self.browse_path_btn.clicked.connect(self.browse_custom_path)
        self.browse_path_btn.setEnabled(False)
        custom_path_layout.addWidget(self.browse_path_btn)

        output_layout.addLayout(custom_path_layout)
        left_layout.addWidget(output_group)

        # 转换选项组
        options_group = QGroupBox("转换选项")
        options_layout = QVBoxLayout(options_group)
        options_layout.setSpacing(6)
        options_layout.setContentsMargins(8, 16, 8, 8)

        # 质量设置
        quality_layout = QHBoxLayout()
        quality_layout.setSpacing(6)
        quality_label = QLabel('质量:')
        quality_label.setFixedWidth(40)
        quality_layout.addWidget(quality_label)

        self.quality_slider = QSlider(Qt.Horizontal)
        self.quality_slider.setMinimum(1)
        self.quality_slider.setMaximum(100)
        self.quality_slider.setValue(80)
        self.quality_slider.setTickPosition(QSlider.TicksBelow)
        self.quality_slider.setTickInterval(10)
        quality_layout.addWidget(self.quality_slider)

        self.quality_label = QLabel('80')
        self.quality_label.setFixedWidth(25)
        self.quality_label.setAlignment(Qt.AlignCenter)
        quality_layout.addWidget(self.quality_label)

        self.quality_slider.valueChanged.connect(
            lambda value: self.quality_label.setText(str(value)))
        self.quality_slider.valueChanged.connect(self.update_size_estimation)

        options_layout.addLayout(quality_layout)

        # 大图像处理选项
        self.auto_resize_checkbox = QCheckBox("自动调整超大图像尺寸")
        self.auto_resize_checkbox.setChecked(True)
        self.auto_resize_checkbox.stateChanged.connect(self.update_size_estimation)
        options_layout.addWidget(self.auto_resize_checkbox)

        # 自动重命名选项
        self.auto_rename_checkbox = QCheckBox("自动重命名文件（添加_converted后缀）")
        self.auto_rename_checkbox.setChecked(False)
        options_layout.addWidget(self.auto_rename_checkbox)

        left_layout.addWidget(options_group)

        # 文件列表
        file_list_label = QLabel("拖放图片到此区域或使用上方按钮添加:")
        left_layout.addWidget(file_list_label)

        self.file_list_widget = QListWidget()
        self.file_list_widget.setSelectionMode(QListWidget.ExtendedSelection)
        self.file_list_widget.itemSelectionChanged.connect(self.show_preview)
        left_layout.addWidget(self.file_list_widget)

        # 大小估算信息
        self.size_estimation_label = QLabel("没有文件可转换")
        self.size_estimation_label.setAlignment(Qt.AlignCenter)
        self.size_estimation_label.setStyleSheet("background-color: #E8E8E8; border: 1px solid #808080; padding: 4px;")
        left_layout.addWidget(self.size_estimation_label)

        # 底部按钮布局
        bottom_layout = QHBoxLayout()
        bottom_layout.setSpacing(4)

        self.convert_btn = QPushButton('开始转换')
        self.convert_btn.clicked.connect(self.start_conversion)
        self.convert_btn.setEnabled(False)
        bottom_layout.addWidget(self.convert_btn)

        self.stop_btn = QPushButton('停止转换')
        self.stop_btn.clicked.connect(self.stop_conversion)
        self.stop_btn.setEnabled(False)
        bottom_layout.addWidget(self.stop_btn)

        left_layout.addLayout(bottom_layout)

        # 进度条
        progress_layout = QVBoxLayout()
        progress_layout.setSpacing(4)
        progress_layout.addWidget(QLabel('转换进度:'))

        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        progress_layout.addWidget(self.progress_bar)

        self.progress_label = QLabel('')
        self.progress_label.setVisible(False)
        progress_layout.addWidget(self.progress_label)

        left_layout.addLayout(progress_layout)

        # 右侧面板（图片预览和信息）
        right_widget = QWidget()
        right_layout = QVBoxLayout(right_widget)
        right_layout.setSpacing(6)
        right_layout.setContentsMargins(4, 4, 4, 4)

        # 图片预览区域
        preview_group = QGroupBox("图片预览")
        preview_layout = QVBoxLayout(preview_group)
        preview_layout.setContentsMargins(8, 16, 8, 8)

        self.preview_label = QLabel()
        self.preview_label.setAlignment(Qt.AlignCenter)
        self.preview_label.setMinimumSize(300, 300)
        self.preview_label.setStyleSheet("background-color: white; border: 2px solid #808080;")
        self.preview_label.setText("选择图片查看预览")
        preview_layout.addWidget(self.preview_label)

        right_layout.addWidget(preview_group)

        # 图片信息
        info_group = QGroupBox("图片信息")
        info_layout = QVBoxLayout(info_group)
        info_layout.setContentsMargins(8, 16, 8, 8)

        self.image_info_label = QLabel("图片信息将显示在这里")
        self.image_info_label.setAlignment(Qt.AlignLeft)
        self.image_info_label.setWordWrap(True)
        info_layout.addWidget(self.image_info_label)

        right_layout.addWidget(info_group)

        # 转换结果表格
        results_group = QGroupBox("转换结果")
        results_layout = QVBoxLayout(results_group)
        results_layout.setContentsMargins(8, 16, 8, 8)

        self.results_table = QTableWidget()
        self.results_table.setColumnCount(5)
        self.results_table.setHorizontalHeaderLabels(["文件名", "原始大小", "转换后大小", "节省大小", "节省百分比"])
        self.results_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.results_table.setVisible(False)
        results_layout.addWidget(self.results_table)

        right_layout.addWidget(results_group)

        # 添加到分割器
        splitter.addWidget(left_widget)
        splitter.addWidget(right_widget)
        splitter.setSizes([600, 600])  # 设置初始分割比例

        main_layout.addWidget(splitter)

    def dragEnterEvent(self, event: QDragEnterEvent):
        """处理拖拽进入事件"""
        if event.mimeData().hasUrls():
            event.acceptProposedAction()

    def dropEvent(self, event: QDropEvent):
        """处理拖放事件"""
        urls = event.mimeData().urls()
        for url in urls:
            file_path = url.toLocalFile()
            if os.path.isfile(file_path) and self.is_image_file(file_path):
                self.add_file_to_list(file_path)

        # 启用转换按钮
        self.convert_btn.setEnabled(len(self.file_list) > 0)
        # 更新大小估算
        self.update_size_estimation()
        event.acceptProposedAction()

    def is_image_file(self, file_path):
        """检查文件是否为图片"""
        image_extensions = ('.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.tif', '.gif', '.webp')
        return file_path.lower().endswith(image_extensions)

    def add_file_to_list(self, file_path):
        """添加文件到列表"""
        # 检查是否已存在
        for existing_path, _ in self.file_list:
            if existing_path == file_path:
                return

        # 获取文件所在目录
        file_dir = os.path.dirname(file_path)
        self.file_list.append((file_path, file_dir))

        # 添加文件到列表控件
        item = QListWidgetItem(os.path.basename(file_path))
        item.setData(Qt.UserRole, file_path)  # 存储完整路径
        self.file_list_widget.addItem(item)

        # 更新总大小
        try:
            file_size = os.path.getsize(file_path)
            self.total_original_size += file_size
        except:
            pass

    def get_file_compression_ratio(self, file_path, quality, auto_resize):
        """根据文件类型和质量获取压缩率估算"""
        try:
            # 获取文件扩展名
            ext = os.path.splitext(file_path)[1].lower()

            # 根据文件类型和质量设置不同的压缩率
            if ext in ['.png', '.bmp', '.tiff', '.tif']:
                # 无损格式转换为有损格式，压缩率更高
                # 使用非线性公式：压缩率 = 0.8 - (quality/100)^2 * 0.5
                compression_ratio = 0.8 - (quality / 100) ** 2 * 0.5

                # 对于PNG，如果包含透明通道，压缩率会更高
                try:
                    img = Image.open(file_path)
                    if img.mode in ('RGBA', 'LA'):
                        compression_ratio *= 1.1  # 增加10%的压缩率
                except:
                    pass

            elif ext in ['.jpg', '.jpeg']:
                # JPEG已经是有损格式，转换为WebP的压缩率较低
                # 使用非线性公式：压缩率 = 0.3 - (quality/100)^2 * 0.2
                compression_ratio = 0.3 - (quality / 100) ** 2 * 0.2

            elif ext == '.gif':
                # GIF通常包含动画，转换为WebP后压缩率中等
                compression_ratio = 0.5 - (quality / 100) ** 2 * 0.3

            else:
                # 其他格式使用默认压缩率
                compression_ratio = 0.4 - (quality / 100) ** 2 * 0.2

            # 确保压缩率在合理范围内
            compression_ratio = max(0.1, min(0.9, compression_ratio))

            # 如果启用了自动调整大小，进一步减少估算大小
            if auto_resize:
                try:
                    img = Image.open(file_path)
                    # 如果图像尺寸大于阈值，应用额外的压缩率
                    if img.width > 4000 or img.height > 4000:
                        compression_ratio *= 1.2  # 增加20%的压缩率
                except:
                    pass

            return compression_ratio

        except Exception as e:
            print(f"Error estimating compression ratio for {file_path}: {str(e)}")
            # 出错时使用默认压缩率
            return 0.4 - (quality / 100) ** 2 * 0.2

    def update_size_estimation(self):
        """更新大小估算信息"""
        if not self.file_list:
            self.size_estimation_label.setText("没有文件可转换")
            return

        quality = self.quality_slider.value()
        auto_resize = self.auto_resize_checkbox.isChecked()

        total_original = 0
        total_estimated = 0

        # 对每个文件单独估算
        for file_path, _ in self.file_list:
            try:
                file_size = os.path.getsize(file_path)
                total_original += file_size

                # 获取该文件的压缩率
                compression_ratio = self.get_file_compression_ratio(file_path, quality, auto_resize)

                # 计算估算大小
                estimated_size = file_size * (1 - compression_ratio)
                total_estimated += estimated_size
            except:
                pass

        self.total_original_size = total_original

        # 计算总节省百分比
        if total_original > 0:
            total_saved_percent = ((total_original - total_estimated) / total_original) * 100
        else:
            total_saved_percent = 0

        # 格式化大小显示
        def format_size(size_bytes):
            if size_bytes < 1024:
                return f"{size_bytes:.0f} B"
            elif size_bytes < 1024 * 1024:
                return f"{size_bytes / 1024:.1f} KB"
            elif size_bytes < 1024 * 1024 * 1024:
                return f"{size_bytes / (1024 * 1024):.1f} MB"
            else:
                return f"{size_bytes / (1024 * 1024 * 1024):.2f} GB"

        original_formatted = format_size(total_original)
        estimated_formatted = format_size(total_estimated)

        # 更新估算标签
        self.size_estimation_label.setText(
            f"原始总大小: {original_formatted} | "
            f"估算转换后: {estimated_formatted} | "
            f"估算节省: {total_saved_percent:.1f}%"
        )

    def show_preview(self):
        """显示选中图片的预览"""
        selected_items = self.file_list_widget.selectedItems()
        if not selected_items:
            self.preview_label.setText("选择图片查看预览")
            self.image_info_label.setText("图片信息将显示在这里")
            return

        # 只显示第一个选中图片的预览
        item = selected_items[0]
        file_path = item.data(Qt.UserRole)

        try:
            # 加载图片
            img = Image.open(file_path)

            # 调整图片大小以适应预览区域
            max_size = 300
            if img.width > max_size or img.height > max_size:
                if img.width > img.height:
                    new_width = max_size
                    new_height = int(img.height * max_size / img.width)
                else:
                    new_height = max_size
                    new_width = int(img.width * max_size / img.height)

                img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)

            # 转换为QPixmap并显示
            img.save("temp_preview.png", "PNG")
            pixmap = QPixmap("temp_preview.png")
            self.preview_label.setPixmap(pixmap)

            # 显示图片信息
            info_text = f"文件名: {os.path.basename(file_path)}\n"
            info_text += f"尺寸: {img.width} x {img.height}\n"
            info_text += f"格式: {img.format}\n"
            info_text += f"模式: {img.mode}\n"
            info_text += f"文件大小: {os.path.getsize(file_path) / 1024:.1f} KB"

            self.image_info_label.setText(info_text)

            # 删除临时文件
            if os.path.exists("temp_preview.png"):
                os.remove("temp_preview.png")

        except Exception as e:
            self.preview_label.setText("无法加载预览")
            self.image_info_label.setText(f"错误: {str(e)}")

    def toggle_path_option(self):
        """切换路径选项"""
        if self.custom_path_radio.isChecked():
            self.custom_path_edit.setEnabled(True)
            self.browse_path_btn.setEnabled(True)
        else:
            self.custom_path_edit.setEnabled(False)
            self.browse_path_btn.setEnabled(False)

    def browse_custom_path(self):
        """浏览自定义路径"""
        path = QFileDialog.getExistingDirectory(self, '选择输出目录')
        if path:
            self.custom_path_edit.setText(path)

    def select_files(self):
        """选择单个或多个图片文件"""
        files, _ = QFileDialog.getOpenFileNames(
            self, '选择图片文件', '',
            '图片文件 (*.jpg *.jpeg *.png *.bmp *.tiff *.tif *.gif *.webp)'
        )

        if files:
            for file_path in files:
                self.add_file_to_list(file_path)

            # 启用转换按钮
            self.convert_btn.setEnabled(len(self.file_list) > 0)
            # 更新大小估算
            self.update_size_estimation()

    def select_folder(self):
        """选择包含图片的文件夹"""
        folder = QFileDialog.getExistingDirectory(self, '选择图片文件夹')
        if folder:
            # 清空当前列表
            self.clear_file_list()

            # 加载文件夹中的所有图片
            image_extensions = ('.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.tif', '.gif', '.webp')

            for file_name in os.listdir(folder):
                if file_name.lower().endswith(image_extensions):
                    file_path = os.path.join(folder, file_name)
                    self.add_file_to_list(file_path)

            # 启用转换按钮
            self.convert_btn.setEnabled(len(self.file_list) > 0)
            # 更新大小估算
            self.update_size_estimation()

    def clear_file_list(self):
        """清空文件列表"""
        self.file_list_widget.clear()
        self.file_list = []
        self.total_original_size = 0
        self.convert_btn.setEnabled(False)
        self.preview_label.setText("选择图片查看预览")
        self.image_info_label.setText("图片信息将显示在这里")
        # 清空结果表格
        self.results_table.setRowCount(0)
        self.results_table.setVisible(False)
        # 更新大小估算
        self.update_size_estimation()

    def start_conversion(self):
        """开始转换过程"""
        if not self.file_list:
            QMessageBox.warning(self, '警告', '没有可转换的图片文件!')
            return

        # 检查自定义路径是否有效
        output_dir = None
        if self.custom_path_radio.isChecked():
            custom_path = self.custom_path_edit.text()
            if not custom_path:
                QMessageBox.warning(self, '警告', '请选择或输入自定义输出路径!')
                return
            output_dir = custom_path

        # 清空之前的转换结果
        self.conversion_results = []
        self.results_table.setRowCount(0)
        self.results_table.setVisible(True)

        # 禁用UI控件
        self.select_files_btn.setEnabled(False)
        self.select_folder_btn.setEnabled(False)
        self.clear_list_btn.setEnabled(False)
        self.convert_btn.setEnabled(False)
        self.stop_btn.setEnabled(True)

        # 显示进度条
        self.progress_bar.setVisible(True)
        self.progress_label.setVisible(True)
        self.progress_bar.setMaximum(len(self.file_list))
        self.progress_bar.setValue(0)
        self.progress_label.setText('准备开始...')

        # 创建并启动转换线程
        quality = self.quality_slider.value()
        auto_resize = self.auto_resize_checkbox.isChecked()
        auto_rename = self.auto_rename_checkbox.isChecked()

        self.conversion_thread = ConversionThread(
            self.file_list, output_dir, quality, auto_resize, auto_rename)
        self.conversion_thread.progress_updated.connect(self.update_progress)
        self.conversion_thread.conversion_finished.connect(self.conversion_complete)
        self.conversion_thread.file_converted.connect(self.add_conversion_result)
        self.conversion_thread.start()

    def stop_conversion(self):
        """停止转换过程"""
        if self.conversion_thread and self.conversion_thread.isRunning():
            self.conversion_thread.stop()
            self.conversion_thread.wait()

        self.reset_ui()
        self.progress_label.setText('转换已停止')

    def update_progress(self, current, total, file_name):
        """更新进度显示"""
        self.progress_bar.setValue(current)
        self.progress_label.setText(f'正在转换: {file_name} ({current}/{total})')

    def add_conversion_result(self, file_name, original_size, new_size, saved_percent):
        """添加转换结果到表格"""
        row_position = self.results_table.rowCount()
        self.results_table.insertRow(row_position)

        # 计算节省的大小
        saved_size = original_size - new_size

        # 格式化文件大小显示
        def format_size(size_bytes):
            if size_bytes < 1024:
                return f"{size_bytes} B"
            elif size_bytes < 1024 * 1024:
                return f"{size_bytes / 1024:.2f} KB"
            else:
                return f"{size_bytes / (1024 * 1024):.2f} MB"

        # 添加数据到表格
        self.results_table.setItem(row_position, 0, QTableWidgetItem(file_name))
        self.results_table.setItem(row_position, 1, QTableWidgetItem(format_size(original_size)))
        self.results_table.setItem(row_position, 2, QTableWidgetItem(format_size(new_size)))
        self.results_table.setItem(row_position, 3, QTableWidgetItem(format_size(saved_size)))
        self.results_table.setItem(row_position, 4, QTableWidgetItem(f"{saved_percent:.2f}%"))

        # 存储结果
        self.conversion_results.append({
            'file_name': file_name,
            'original_size': original_size,
            'new_size': new_size,
            'saved_percent': saved_percent
        })

    def conversion_complete(self):
        """转换完成处理"""
        self.reset_ui()
        self.progress_label.setText('转换完成!')

        # 计算总计节省
        if self.conversion_results:
            total_original = sum(r['original_size'] for r in self.conversion_results)
            total_new = sum(r['new_size'] for r in self.conversion_results)
            total_saved_percent = ((total_original - total_new) / total_original) * 100

            # 添加总计行
            row_position = self.results_table.rowCount()
            self.results_table.insertRow(row_position)

            # 格式化文件大小显示
            def format_size(size_bytes):
                if size_bytes < 1024:
                    return f"{size_bytes} B"
                elif size_bytes < 1024 * 1024:
                    return f"{size_bytes / 1024:.2f} KB"
                else:
                    return f"{size_bytes / (1024 * 1024):.2f} MB"

            self.results_table.setItem(row_position, 0, QTableWidgetItem("总计"))
            self.results_table.setItem(row_position, 1, QTableWidgetItem(format_size(total_original)))
            self.results_table.setItem(row_position, 2, QTableWidgetItem(format_size(total_new)))
            self.results_table.setItem(row_position, 3, QTableWidgetItem(format_size(total_original - total_new)))
            self.results_table.setItem(row_position, 4, QTableWidgetItem(f"{total_saved_percent:.2f}%"))

            # 设置总计行样式
            for col in range(5):
                item = self.results_table.item(row_position, col)
                if item:
                    item.setBackground(QColor(212, 208, 200))
                    font = item.font()
                    font.setBold(True)
                    item.setFont(font)

        QMessageBox.information(self, '完成', '所有图片已成功转换为WebP格式!')

    def reset_ui(self):
        """重置UI状态"""
        # 重新启用UI控件
        self.select_files_btn.setEnabled(True)
        self.select_folder_btn.setEnabled(True)
        self.clear_list_btn.setEnabled(True)
        self.convert_btn.setEnabled(len(self.file_list) > 0)
        self.stop_btn.setEnabled(False)

    def closeEvent(self, event):
        """窗口关闭事件处理"""
        if self.conversion_thread and self.conversion_thread.isRunning():
            self.conversion_thread.stop()
            self.conversion_thread.wait()
        event.accept()


if __name__ == '__main__':
    app = QApplication(sys.argv)

    # 忽略Pillow的DecompressionBombWarning
    warnings.filterwarnings("ignore", category=Image.DecompressionBombWarning)

    converter = ImageConverter()
    converter.show()

    sys.exit(app.exec_())